/*************************************************************************
 *
*    Used with ICCARM and AARM.
 *
 *    (c) Copyright IAR Systems 2007
 *
 *    File name   : lcd_drv.c
 *    Description : Graphical LCD driver
 *
 *    History :
 *    1. Date        : 6, March 2008
 *       Author      : Stanimir Bonev
 *       Description : Create
 *
 *
 *    $Revision: 1.1 $
 **************************************************************************/
/*
EDITED BY
 ####        # 
 #           #
 ## ### #  # #
 #  #-# #\ # #
 #  # # # \# ####
 Author: Felipe de Andrade Neves Lavratti

 Copyright: There are no restrictions. Use as you want.	  
*/

/*
	LPC 2478
	+ TFT DISPLAY
	+ TOUCH PANNEL
	+ SWIM
	+ SDRAM

	Get more at: selivre.wordpress.com
*/

#include "lcd_driver.h"


/*************************************************************************
 * Function Name: LCD_Cursor_Cnfg
 * Parameters: 
 *             
 * Return: none
 *
 * Description: Configure the cursor
 *
 *************************************************************************/
void LCD_Cursor_Cfg(int Cfg)
{
  CRSR_CFG = Cfg;

}
/*************************************************************************
 * Function Name: LCD_Cursor_En
 * Parameters: cursor - Cursor Number
 *             
 * Return: none
 *
 * Description: Enable Cursor 
 *
 *************************************************************************/
void LCD_Cursor_En(int cursor)
{
  /* Set Cursor and enable */
  CRSR_CTRL = ( cursor & 0x30 ) | 0x1;
}

/*************************************************************************
 * Function Name: LCD_Cursor_Dis
 * Parameters: None
 *             
 * Return: none
 *
 * Description: Disable Cursor
 *
 *************************************************************************/
void LCD_Cursor_Dis(int cursor)
{
  CRSR_CTRL &= ~(0x1);
}

/*************************************************************************
 * Function Name: LCD_Move_Cursor
 * Parameters: x - cursor x position
 *             y - cursor y position
 *            
 * Return: none
 *
 * Description: Moves cursor on position (x,y). Negativ values are posible.
 *
 *************************************************************************/
void LCD_Move_Cursor(int x, int y)
{
  CRSR_XY = 0;
  CRSR_XY |= (x-32) & 0x3FF;
  CRSR_XY |= ((y-32) & 0x3FF )<<16;

}

/*************************************************************************
 * Function Name: LCD_Copy_Cursor
 * Parameters: pCursor - pointer to cursor conts image
 *             cursor - cursor Number (0,1,2 or 3)
 *                      for 64x64(size 256) pix cursor always use 0
 *             size - cursor size in words
 * Return: none
 *
 * Description: Copy Cursor from const image to LCD RAM image
 *
 *************************************************************************/
void LCD_Copy_Cursor (const UNS_32 *pCursor, int cursor, int size)
{
   int i;
   UNS_32 * pDst = (UNS_32 *)LCD_CURSOR_BASE_ADDR;
   pDst += cursor*64;
   
   for(i = 0; i < size ; i++) *pDst++ = *pCursor++;
}

void LCD_Change_Page (const UNS_16 *pPain, const UNS_32 pPage) //16 bits mode
{
	  pUNS_16 pDst = (pUNS_16) (LCD_VRAM_BASE_ADDR + (pPage * C_LCD_PAGE_SIZE));
	  int i,j;

	  // Frame Base Address doubleword aligned
	  LCD_UPBASE         =  (LCD_VRAM_BASE_ADDR + (pPage * C_LCD_PAGE_SIZE)) & ~7;
	  LCD_LPBASE         =  (LCD_VRAM_BASE_ADDR + (pPage * C_LCD_PAGE_SIZE)) & ~7;

	  if (NULL != pPain)
	  {
	    // set display memory
	    for(i = 0; (C_LCD_H_SIZE * C_LCD_V_SIZE) > i; i++)
	    {
	    	*pDst++ = *pPain++;
	    	for(j=10;j;j--);
	    }
	  }
//	  for(i = C_LCD_ENA_DIS_DLY; i; i--);

}
/*************************************************************************
 * Function Name: LCD_Init
 * Parameters: const Int32U *pPain, const Int32U * pPallete
 *
 * Return: none
 *
 * Description: LCD controller init
 *
 *************************************************************************/
void LCD_Init(const UNS_32 *pPain, const UNS_32 * pPallete, const UNS_32 pPage)
{
pUNS_32 pDst = (pUNS_32) (LCD_VRAM_BASE_ADDR + (pPage * C_LCD_PAGE_SIZE));
UNS_32 i;

  // Assign pin
  PINSEL0 &= 0xFFF000FF;
  PINSEL0 |= 0x00055500;
  PINMODE0&= 0xFFFC00FF;
  PINMODE0|= 0x0002AA00;
  PINSEL3 &= 0xF00000FF;
  PINSEL3 |= 0x05555500;
  PINMODE3&= 0xF00000FF;
  PINMODE3|= 0x0AAAAA00;
  PINSEL4 &= 0xF0300000;
  PINSEL4 |= 0x054FFFFF;
  PINMODE4&= 0xF0300000;
  PINMODE4|= 0x0A8AAAAA;
  PINSEL9 &= 0xF0FFFFFF;
  PINSEL9 |= 0x0A000000;
  PINMODE9&= 0xF0FFFFFF;
  PINMODE9|= 0x0A000000;
  PINSEL11&= 0xFFFFFFF0;
  PINSEL11|= 0x0000000F;

  // Init LCD cotroller
  PCONP     |= 1 << 20;          // enable LCD controller clock
  CRSR_CTRL &= ~ 0x1;     	  // Disable cursor

  // disable LCD controller
  // 24 bpp
  // TFT panel
  // single panel
  // normal output
  // little endian byte order
  // little endian pix order
  // disable power
//  LCD_CTRL  =  0x0000002A;   //24bits
  LCD_CTRL  =  0x0000012C; //16bits 565 mode

  // init pixel clock
  LCD_CFG = 0x08 & 0x000001F ;
  LCD_CFG =  (UNS_32)CPU_CLOCK_HZ / (UNS_32)C_LCD_PIX_CLK;

  // bypass inrenal clk divider
  // clock source for the LCD block is HCLK
  // LCDFP pin is active LOW and inactive HIGH
  // LCDLP pin is active LOW and inactive HIGH
  // data is driven out into the LCD on the falling edge
  // active high
  LCD_POL = 0x04003800;
  LCD_POL |= (C_LCD_H_SIZE-1) << 16;

  // init Horizontal Timing
  LCD_TIMH = 0x00000000;
  LCD_TIMH |=  (C_LCD_H_BACK_PORCH - 1) << 24;
  LCD_TIMH |=  (C_LCD_H_FRONT_PORCH - 1)<< 16;
  LCD_TIMH |=  (C_LCD_H_PULSE - 1)      <<  8;
  LCD_TIMH |=  ((C_LCD_H_SIZE/16) - 1)  <<  2;

  // init Vertical Timing
  LCD_TIMV = 0x00000000;
  LCD_TIMV |=  (C_LCD_V_BACK_PORCH)  << 24;
  LCD_TIMV |=  (C_LCD_V_FRONT_PORCH) << 16;
  LCD_TIMV |=  (C_LCD_V_PULSE)       << 10;
  LCD_TIMV |=  (C_LCD_V_SIZE - 1);

  // Frame Base Address doubleword aligned
  LCD_UPBASE         =  (LCD_VRAM_BASE_ADDR + (pPage * C_LCD_PAGE_SIZE)) & ~7;

  // init colour pallet
  if(NULL != pPallete)
  {
    LCD_SetPallet(pPallete);
  }
  if (NULL == pPain)
  {
    // clear display memory
    for(i = 0; (C_LCD_H_SIZE * C_LCD_V_SIZE) > i; i++)
    {
      *pDst++ = 0;
    }
  }
  else
  {
    // set display memory
    for(i = 0; (C_LCD_H_SIZE * C_LCD_V_SIZE) > i; i++)
    {
      *pDst++ = *pPain++;
    }
  }
  for(i = C_LCD_ENA_DIS_DLY; i; i--);
}

/*************************************************************************
 * Function Name: LCD_SetPallet
 * Parameters: const Int32U * pPallete
 *
 * Return: none
 *
 * Description: LCD init colour pallete
 *
 *************************************************************************/
void LCD_SetPallet (const UNS_32 * pPallete)
{
UNS_32 i;
pUNS_32 pDst = (pUNS_32)LCD_PAL;
  if(!pPallete) return;
  for (i = 0; i < 128; i++)
  {
    *pDst++ = *pPallete++;
  }
}

/*************************************************************************
 * Function Name: LCD_Ctrl
 * Parameters: Boolean bEna
 *
 * Return: none
 *
 * Description: LCD enable disabe sequence
 *
 *************************************************************************/
void LCD_Ctrl (BOOL_32 bEna)
{
volatile UNS_32 i;
  if (bEna)
  {
    LCD_CTRL |= 0x1;
    for( i = C_LCD_PWR_ENA_DIS_DLY; i; i--);
    LCD_CTRL |= (0x1<<11);   // enable power
  }
  else
  {
    LCD_CTRL &= ~(0x1<<11);   // disable power
    for( i = C_LCD_PWR_ENA_DIS_DLY; i; i--);
    LCD_CTRL &= ~0x1;
  }
}

